package com.yang.sso.oauth.security;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.json.JSONUtil;

import com.yang.sso.oauth.oauth.exception.MyAccessDeniedHandler;
import com.yang.sso.oauth.oauth.exception.MyAuthenticationEntryPoint;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

import java.util.ArrayList;
import java.util.List;


/**
 * @author: Islands
 * @create: 2024-04-11 14:41
 */
@Slf4j
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
@ConfigurationProperties(prefix = "security")
@EnableGlobalMethodSecurity(prePostEnabled = true,securedEnabled = true)
public class MySecurityConfig extends WebSecurityConfigurerAdapter {

    private List<String> whitePaths;

    public void setWhitePaths(List<String> whitePaths) {
        this.whitePaths = whitePaths;
    }

    /**
     * 用户安全策略
     * @param http the {@link HttpSecurity} to modify
     * @throws Exception 授权异常
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.formLogin().and().authorizeRequests((request) -> {
                            if (CollectionUtil.isNotEmpty(whitePaths)) {
                                request.antMatchers(Convert.toStrArray(whitePaths)).permitAll()
                                        .anyRequest().authenticated();
                            }
                            log.info("默认放行路由:{}", JSONUtil.toJsonStr(whitePaths));
                        }
                )
                // 基于token，所以不需要session
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and().exceptionHandling()
                //身份验证入口点
                .authenticationEntryPoint(new MyAuthenticationEntryPoint())
                //访问被拒绝的处理程序
                .accessDeniedHandler(new MyAccessDeniedHandler())
                .and().httpBasic()
                .and().cors().and().csrf(AbstractHttpConfigurer::disable);



    }

    /**
     * 从父类加载认证过管理器
     * @return AuthenticationManager
     * @throws Exception 认证异常
     */
    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
}
